<!--
 * @Description: 
 * @Author: huxianc
 * @Date: 2020-12-08 11:42:13
 * @LastEditors: huxianc
 * @LastEditTime: 2020-12-18 13:51:41
-->
<template>
  <div id="app">
    <div class="form" v-if="false">
      <input type="text" v-model="form.x" placeholder="x" />
      <input type="text" v-model="form.y" placeholder="y" />
      <button @click="handleClick">提交</button>
    </div>
    <div id="container"></div>
  </div>
</template>

<script>
import Konva from "konva";
export default {
  name: "App",
  components: {},
  data() {
    return {
      stage: null,
      layer: null,
      sx: 0,
      sy: 0,
      scale: 0,
      status: {
        draggable: false
      },
      mapImg: null,
      form: {
        x: "100",
        y: "500"
      },
      ws: null,
      personList: [],
      mapId: "1",
      person: {
        all: [],
        current: []
      }
    };
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      this.stage = new Konva.Stage({
        x: 0,
        y: 0,
        width: window.innerWidth,
        height: window.innerHeight,
        container: "container",
        scale: {
          x: this.scale,
          y: this.scale
        }
      });

      this.stageEventsInit();

      this.layer = new Konva.Layer();
      this.stage.add(this.layer);

      this.initShape();
    },
    initShape() {
      const bg = new Image();
      bg.src = "/images/bg.png";
      bg.onload = async () => {
        const image = new Konva.Image({
          image: bg,
          name: "bg-img",
          width: bg.width,
          height: bg.height
        });

        this.minScale = (window.innerWidth * 0.5) / image.width();
        this.scale = Number((window.innerWidth / image.width()).toFixed(2));

        await this.layer.add(image);
        this.stage.setAttrs({
          scale: {
            x: this.scale,
            y: this.scale
          }
        });
        image.moveToBottom();
        await this.layer.batchDraw();
        this.mapImg = image;
        this.initWS();
      };
    },
    handleClick() {
      if (this.form.x === "" || this.form.y === "") return;
      const image = new Image();
      image.src = "/images/staff_unchecked0.png";
      image.onload = async () => {
        const person = new Konva.Image({
          image: image,
          x: Number(this.form.x),
          y: Number(this.form.y)
        });

        this.layer.add(person);
        this.layer.batchDraw();
      };
    },
    getLocation(str) {
      const [x, y] = str.split(",").map(location => Number(location));
      return {
        x,
        y
      };
    },
    initPerson(attrs) {
      const { x, y, TagId } = attrs;
      const image = new Image();
      image.src = "/images/staff_unchecked0.png";
      if (TagId === "1002") {
        image.src = "/images/staff_unchecked1.png";
      }
      image.onload = async () => {
        const person = new Konva.Image({
          image: image,
          x,
          y,
          name: String(TagId)
        });

        this.layer.add(person);
        this.layer.batchDraw();
      };
    },
    initWS() {
      this.ws = new WebSocket("WS://192.168.1.248:6010/tag");

      this.ws.onmessage = async event => {
        const data = JSON.parse(event.data);
        // console.log(data);
        if (data.ActionCode === 1003 && data.Data.TagId === "1002") {
          console.log(data.Data);
        }
        /**
         * 1000 标签初始化
         * 1001 单个标签上线
         * 1002 单个标签下线
         * 1003 单个标签移动
         */
        if (data.ActionCode === 1000) {
          // 初始化
          this.person.all =
            data.Data.map(item => {
              const { x, y } = this.getLocation(item.LocationSceneId);
              return {
                ...item,
                x,
                y
              };
            }) || [];
          this.person.current = this.person.all.filter(
            item => item.LocationSceneId === this.mapId
          );
          this.person.current.forEach(item => {
            this.initPerson(item);
          });
        }

        if (data.ActionCode === 1001) {
          const { x, y } = this.getLocation(data.Data.LocationPoint);
          const obj = {
            ...data.Data,
            x,
            y
          };
          this.person.all.push(obj);
          if (this.mapId === data.Data.LocationSceneId) {
            this.person.current.push(obj);
            this.initPerson(obj);
            console.log(`${obj.TagId}上线！`);
          }
        }

        if (data.ActionCode === 1003) {
          // 判断是否是当前场景
          if (this.mapId === data.Data.LocationSceneId) {
            const node = this.layer.findOne("." + data.Data.TagId);

            if (node) {
              const { x, y } = this.getLocation(data.Data.LocationPoint);
              node.to({
                x,
                y
              });
            }
          }
        }

        // if (this.personList.length > 0) {
        //   const index = this.personList.findIndex(item => {
        //     item.tagId === obj.tagId;
        //   });
        //   if (index > -1) {
        //     this.personList[index] = obj;
        //     const person = this.stage.findOne("." + obj.tagId);
        //     if (person) {
        //       person.to({
        //         x: obj.x,
        //         y: obj.y
        //       });

        //       this.layer.batchDraw();
        //     }
        //   } else {
        //     this.personList.push(obj);
        //     this.initPerson(obj);
        //   }
        // } else {
        //   this.personList.push(obj);
        //   this.initPerson(obj);
        // }
      };
    },
    stageEventsInit() {
      this.handleStageWheel();
      this.handleStageMouseDown();
      this.handleStageMouseUp();
      this.handleStageMouseMove();
    },
    handleStageWheel() {
      this.stage.on("wheel", e => {
        e = e.evt;

        const wheelDelta = e.wheelDelta ? e.wheelDelta : e.deltalY * -40;

        const rateX = (e.clientX - this.sx) / this.scale;
        const rateY = (e.clientY - this.sy) / this.scale;

        if (wheelDelta > 0) {
          if (this.scale >= this.maxScale) {
            this.scale = this.maxScale;
            return;
          }
          this.scale = Number((this.scale + 0.05).toFixed(2));
        } else {
          if (this.scale <= this.minScale) {
            this.scale = this.minScale;
            return;
          }
          this.scale = Number((this.scale - 0.05).toFixed(2));
        }

        this.sx = (1 - this.scale) * rateX + e.clientX - rateX;
        this.sy = (1 - this.scale) * rateY + e.clientY - rateY;

        this.stage.setAttrs({
          x: this.sx,
          y: this.sy,
          scaleX: this.scale,
          scaleY: this.scale
        });

        this.stage.batchDraw();
      });
    },
    handleStageMouseDown() {
      this.stage.on("mousedown", e => {
        // ? 是否需要做 e.target 是 image的判断
        e = e.evt;
        this.status.draggable = true;
        this.mousePos = {
          x: e.clientX,
          y: e.clientY
        };
        this.stage.container().style.cursor = "move";
      });
    },
    handleStageMouseUp() {
      this.stage.on("mouseup mouseout", () => {
        if (this.status.draggable) {
          this.status.draggable = false;
          this.stage.container().style.cursor = "default";
        }
      });
    },
    handleStageMouseMove() {
      this.stage.on("mousemove", e => {
        const mouseMoveFunc = e => {
          e = e.evt;
          // 绘制电子围栏判断
          if (this.status.isDrawFence) {
            const { points } = this.drawFenceInfo;

            if (points.length >= 1) {
              if (points.length > 1) {
                points.pop();
              }
              const pos = this.screenTocanvas({ x: e.clientX, y: e.clientY });
              points.push(pos);
              // points.push({ x: e.clientX, y: e.clientY })
              this.handleStartDrawFence();
            }
            return;
          }
          if (!this.status.draggable) return;
          this.mousePos.x =
            Math.abs(this.mousePos.x - e.clientX) > 1
              ? this.mousePos.x
              : e.clientX;
          this.mousePos.y =
            Math.abs(this.mousePos.y - e.clientY) > 1
              ? this.mousePos.y
              : e.clientY;

          this.sx += e.clientX - this.mousePos.x;
          this.sy += e.clientY - this.mousePos.y;

          const maxSx = this.getOffset(
            {
              x: this.stage.width() * 0.25,
              y: 0
            },
            {
              x: 0,
              y: 0
            },
            this.scale
          ).x;
          const minSx = this.getOffset(
            {
              x: this.stage.width() * 0.75,
              y: 0
            },
            {
              x: this.mapImg.width,
              y: 0
            },
            this.scale
          ).x;
          const maxSy = this.getOffset(
            {
              x: 0,
              y: 0
            },
            {
              x: 0,
              y: 0
            },
            this.scale
          ).y;
          const minSy = this.getOffset(
            {
              x: 0,
              y: this.stage.height()
            },
            {
              x: 0,
              y: this.mapImg.height
            },
            this.scale
          ).y;
          const midSy = this.getOffset(
            {
              x: 0,
              y: this.stage.height() / 2
            },
            {
              x: 0,
              y: this.mapImg.height / 2
            },
            this.scale
          ).y;

          if (maxSx <= minSx) {
            this.sx = maxSx;
          } else if (this.sx > maxSx) {
            this.sx = maxSx;
          } else if (this.sx < minSx) {
            this.sx = minSx;
          }

          if (maxSy <= minSy) {
            this.sy = maxSy;
          } else if (this.sy > maxSy) {
            this.sy = maxSy;
          } else if (this.sy < minSy) {
            this.sy = minSy;
          }

          if (this.scale === this.minScale) {
            this.sy = midSy;
          }

          this.mousePos = {
            x: e.clientX,
            y: e.clientY
          };

          this.stage.setAttrs({
            x: this.sx,
            y: this.sy
          });

          this.stage.batchDraw();
        };

        mouseMoveFunc(e);
      });
    },
    getOffset(canvasPos, imgPos, scale) {
      return {
        x: canvasPos.x - imgPos.x * scale,
        y: canvasPos.y - imgPos.y * scale
      };
    }
  }
};
</script>

<style lang="scss">
html,
body {
  margin: 0;
  padding: 0;
}
.form {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 100;
}
</style>
